package midas.mw.crt;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import midas.mw.cfg.CfgLogging;
import midas.mw.cfg.log.Logger;
import midas.mw.crt.common.IPMessage;

public class MessageReceiver extends Thread 
{
	/**
	 * This class will allow to rebuilt received chunked messages
	 */
	private Hashtable nodes;
	
	/**
	 * Stores the chunked IPMessage from an specific source node with an specific message ID
	 * @param ipMessage Chunked IPMessage to be managed 
	 */
	public void addMessage(IPMessage ipMessage)
	{	
		CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "MessageReceiver.addMessagePart(" + ipMessage.msgToString() + ")");
		
		//En este caso no hace falta sincronizar porque el unico sitio desde el que se la llama es desde
		//PacketForwarder.processIncomingMessage y MessagePipe.pipeMsgEvent y estan sincronizado
				
		Hashtable messagesFromNode = new Hashtable();
		messagesFromNode.put(ipMessage.getMessageId(), ipMessage);
		
		nodes.put(ipMessage.getSourceNodeId(), messagesFromNode);		
	}	
	
	/**
	 * Gets the chunked message associated to the specific source node with the specific message identifier
	 * 
	 * @param nodeId Node ID of the source node of the message
	 * @param messageId Message ID
	 * @return The chunked IPMessage
	 */
	public IPMessage getMessage (String nodeId, Long messageId)
	{
		CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "MessageReceiver.getMessage(" + nodeId + ", " + messageId + ")");
		
		//En este caso no hace falta sincronizar porque el unico sitio desde el que se la llama es desde
		//PacketForwarder.processIncomingMessage y MessagePipe.pipeMsgEvent y estan sincronizado
		IPMessage ipMessage = null;
		Hashtable messagesFromNode = (Hashtable)nodes.get(nodeId);
		if (messagesFromNode != null)
			ipMessage = (IPMessage)messagesFromNode.get(messageId);
		return ipMessage;				
	}
	
	/**
	 * Removes the chunked message associated to the specific source node with the specific message identifier
	 * 
	 * @param nodeId Node ID of the source node of the message
	 * @param messageId Message ID
	 */
	public void removeMessage (String nodeId, Long messageId)
	{
		CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "MessageReceiver.removeMessage(" + nodeId + ", " + messageId + ")");
		
		//En este caso no hace falta sincronizar porque el unico sitio desde el que se la llama es desde
		//PacketForwarder.processIncomingMessage y MessagePipe.pipeMsgEvent y estan sincronizado
		Hashtable messagesFromNode = (Hashtable)nodes.get(nodeId);
		if (messagesFromNode != null)
		{
			messagesFromNode.remove(messageId);
			if (messagesFromNode.isEmpty())
				nodes.remove(nodeId);
		}		
	}
	
	
	/**
	 * Constructor - Create the Message Dispatcher and initializes local variables	 
	 */
	public MessageReceiver() 
	{
		CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "MessageReceiver()");
			
		nodes				= new Hashtable();
	}
	
	/**
	 * Prints the chunked messages stored in the CRT
	 */
	public synchronized void printTable() 
	{
		CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "MessageReceiver.printTable()");
		
		Iterator it = nodes.entrySet().iterator();

		while (it.hasNext()) {
			Map.Entry e = (Map.Entry)it.next();			
			Hashtable messages = (Hashtable)e.getValue();
			Iterator it2 = messages.entrySet().iterator();

			while (it2.hasNext())
			{
				Map.Entry e2 = (Map.Entry)it2.next();
				CfgLogging.logEvent(CfgLogging.LOG_MCALL, Logger.COMPONENT_CRT, CfgLogging.SEV_DEBUG, "MessageReceiver.printTable(): " + e.getKey() + "-- " + e2.getKey());
			}
		}
	}
}